import sys
import time

import numpy as np
from PySide6.QtWidgets import (QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
                               QPushButton, QLabel, QDoubleSpinBox, QComboBox,
                               QCheckBox, QGroupBox, QFrame, QSpinBox)
from PySide6.QtCore import Qt, QTimer, Signal
from PySide6.QtGui import QPainter, QPen, QColor, QFont
import pyqtgraph as pg


class WaveformDisplayWindow(QMainWindow):
    """波形显示窗口"""

    update_waveform_signal = Signal(list, dict)  # 波形数据，参数
    parameter_changed_signal = Signal(str, object)  # 参数名称，参数值
    window_closed = Signal(str)  # 窗口关闭信号，传递节点ID

    def __init__(self, node_name="波形查看器", processor=None, main_window=None):
        super().__init__()
        self.node_name = node_name
        self.processor = processor
        self.main_window = main_window
        self.waveform_data = []
        # 获取节点ID（从处理器或节点名称中提取）
        self.node_id = getattr(processor, 'nodeId', node_name)
        self.display_params = {
            'auto_scale': True,
            'display_time': 1.00,  # 默认值改为1.00
            'y_range': 1.00,  # 默认值改为1.00
            'x_axis_mode': 'time',
            'x_scroll': False,
            'show_grid': True,
            'sample_rate': 44100,
            'refresh_rate': 20  # 默认刷新率20 FPS
        }

        # 性能优化
        self.max_display_points = 2000  # 限制显示点数
        self.last_display_update = 0
        self.display_update_interval = 0.033  # ~30 FPS

        # 防止参数循环更新
        self.updating_from_processor = False
        self.updating_from_ui = False

        # 🔧 移除：运行状态标志（不再需要）
        # self.is_processing_running = False

        self.init_ui()

        # 连接信号
        self.update_waveform_signal.connect(self.on_update_waveform)

        # 设置初始状态
        self.update_controls()

        # 设置处理器回调
        if self.processor:
            self.processor.set_display_window(self)
            self.processor.set_parameter_update_callback(self.on_parameter_updated_from_processor)

    def init_ui(self):
        """初始化UI"""
        self.setWindowTitle(f"波形查看器 - {self.node_name}")
        self.setGeometry(100, 100, 900, 600)

        # 中央部件
        central_widget = QWidget()
        self.setCentralWidget(central_widget)

        # 主布局
        main_layout = QVBoxLayout(central_widget)

        # 控制面板 - 使用分组框组织相关功能
        self.create_display_controls(main_layout)
        self.create_axis_controls(main_layout)

        # 波形显示区域
        self.create_plot_widget(main_layout)

        # 状态栏
        self.create_status_bar(main_layout)

        # 初始显示一些示例数据，避免空白
        self.show_example_data()

    def create_display_controls(self, parent_layout):
        """创建显示控制面板 - 修改范围限制"""
        display_group = QGroupBox("显示设置")
        display_layout = QVBoxLayout(display_group)

        # 第一行：自动缩放和网格显示
        row1_layout = QHBoxLayout()

        # 自动缩放复选框
        self.auto_scale_check = QCheckBox("自动缩放")
        self.auto_scale_check.setChecked(True)
        self.auto_scale_check.toggled.connect(self.on_auto_scale_changed)
        row1_layout.addWidget(self.auto_scale_check)

        # 网格显示复选框
        self.grid_check = QCheckBox("显示网格")
        self.grid_check.setChecked(True)
        self.grid_check.toggled.connect(self.on_grid_changed)
        row1_layout.addWidget(self.grid_check)

        row1_layout.addStretch()
        display_layout.addLayout(row1_layout)

        # 第二行：显示时间和Y轴范围
        row2_layout = QHBoxLayout()

        # 显示时间 - 修改范围：0.01 到 1.00
        row2_layout.addWidget(QLabel("显示时间:"))
        self.display_time_spin = QDoubleSpinBox()
        self.display_time_spin.setRange(0.01, 1.00)  # 修改为 0.01-1.00
        self.display_time_spin.setValue(1.00)  # 默认值改为 1.00
        self.display_time_spin.setSingleStep(0.01)
        self.display_time_spin.setDecimals(2)  # 设置小数点后2位
        self.display_time_spin.setSuffix(" 秒")
        self.display_time_spin.valueChanged.connect(self.on_display_time_changed)
        row2_layout.addWidget(self.display_time_spin)

        # Y轴范围 - 修改范围：0.01 到 1.00
        row2_layout.addWidget(QLabel("Y轴范围:"))
        self.y_range_spin = QDoubleSpinBox()
        self.y_range_spin.setRange(0.01, 1.00)  # 修改为 0.01-1.00
        self.y_range_spin.setValue(1.00)  # 默认值改为 1.00
        self.y_range_spin.setSingleStep(0.01)
        self.y_range_spin.setDecimals(2)  # 设置小数点后2位
        self.y_range_spin.valueChanged.connect(self.on_y_range_changed)
        row2_layout.addWidget(self.y_range_spin)

        row2_layout.addStretch()
        display_layout.addLayout(row2_layout)
        
        # 第三行：刷新率设置
        row3_layout = QHBoxLayout()
        
        # 刷新率选择
        row3_layout.addWidget(QLabel("刷新率:"))
        self.refresh_rate_spin = QSpinBox()
        self.refresh_rate_spin.setRange(5, 20)  # 设置范围为5-20 FPS
        self.refresh_rate_spin.setValue(20)  # 默认值为20 FPS
        self.refresh_rate_spin.setSingleStep(1)
        self.refresh_rate_spin.setSuffix(" FPS")
        self.refresh_rate_spin.valueChanged.connect(self.on_refresh_rate_changed)
        row3_layout.addWidget(self.refresh_rate_spin)
        
        row3_layout.addStretch()
        display_layout.addLayout(row3_layout)

        parent_layout.addWidget(display_group)

    def create_axis_controls(self, parent_layout):
        """创建坐标轴控制面板"""
        axis_group = QGroupBox("坐标轴设置")
        axis_layout = QHBoxLayout(axis_group)

        # X轴坐标模式
        axis_layout.addWidget(QLabel("X轴坐标:"))
        self.x_axis_combo = QComboBox()
        self.x_axis_combo.addItems(["时间", "样本点"])
        self.x_axis_combo.currentTextChanged.connect(self.on_x_axis_changed)
        axis_layout.addWidget(self.x_axis_combo)

        # X轴滚动
        self.x_scroll_check = QCheckBox("X轴滚动")
        self.x_scroll_check.setChecked(False)
        self.x_scroll_check.toggled.connect(self.on_x_scroll_changed)
        axis_layout.addWidget(self.x_scroll_check)

        axis_layout.addStretch()
        parent_layout.addWidget(axis_group)

    def create_plot_widget(self, parent_layout):
        """创建绘图部件"""
        self.plot_widget = pg.PlotWidget()
        self.plot_widget.setBackground('w')
        self.plot_widget.showGrid(x=True, y=True, alpha=0.3)
        self.plot_widget.setLabel('left', '幅度')
        self.plot_widget.setLabel('bottom', '时间', 's')

        # 设置合理的范围限制
        self.plot_widget.setLimits(
            xMin=0,
            xMax=1e6,
            yMin=-20,
            yMax=20,
            minXRange=0.001,
            maxXRange=1e7,
            minYRange=0.001,
            maxYRange=100
        )

        # 使用较细的线条
        self.plot_curve = self.plot_widget.plot(
            pen=pg.mkPen(color='b', width=1)
        )

        parent_layout.addWidget(self.plot_widget)

    def create_status_bar(self, parent_layout):
        """创建状态栏"""
        self.status_label = QLabel("等待数据...")
        self.status_label.setAlignment(Qt.AlignCenter)
        self.status_label.setStyleSheet("QLabel { background-color: #f0f0f0; padding: 5px; }")
        parent_layout.addWidget(self.status_label)

    def show_example_data(self):
        """显示示例数据，避免初始空白"""
        sample_data = np.sin(2 * np.pi * np.linspace(0, 1, 1000))
        x_data = np.linspace(0, 1, 1000)
        self.plot_curve.setData(x_data, sample_data)
        self.status_label.setText("等待音频数据...")

    def update_controls(self):
        """更新控制状态"""
        params = self.display_params

        # 防止循环更新
        if self.updating_from_processor:
            return

        self.updating_from_ui = True

        self.auto_scale_check.setChecked(params.get('auto_scale', True))
        self.display_time_spin.setValue(params.get('display_time', 1.0))
        self.y_range_spin.setValue(params.get('y_range', 1.0))
        self.refresh_rate_spin.setValue(params.get('refresh_rate', 20))

        x_axis_mode = params.get('x_axis_mode', 'time')
        self.x_axis_combo.setCurrentText("时间" if x_axis_mode == 'time' else "样本点")

        self.x_scroll_check.setChecked(params.get('x_scroll', False))
        self.grid_check.setChecked(params.get('show_grid', True))

        # 根据自动缩放状态启用/禁用范围控制
        auto_scale = params.get('auto_scale', True)
        self.y_range_spin.setEnabled(not auto_scale)

        self.updating_from_ui = False
        
    def on_refresh_rate_changed(self, value):
        """刷新率改变"""
        if self.updating_from_ui:
            return

        self.display_params['refresh_rate'] = value

        # 通知处理器参数改变
        if self.processor and not self.updating_from_processor:
            self.processor.update_parameter_from_display('refresh_rate', value)

    def on_update_waveform(self, waveform_data, params):
        """更新波形显示"""
        current_time = time.time()
        if current_time - self.last_display_update < self.display_update_interval:
            return

        self.last_display_update = current_time

        # 限制数据点数，提高性能
        if len(waveform_data) > self.max_display_points:
            step = len(waveform_data) // self.max_display_points
            waveform_data = waveform_data[::step]

        self.waveform_data = waveform_data
        self.display_params.update(params)

        # 更新控制状态
        self.update_controls()

        if not waveform_data:
            self.status_label.setText("无波形数据")
            return

        # 更新显示
        self.update_display()

    def update_display(self):
        """更新波形显示"""
        if not self.waveform_data:
            return

        params = self.display_params
        waveform = np.array(self.waveform_data, dtype=np.float64)

        # 创建X轴数据
        if params.get('x_axis_mode') == 'time':
            sample_rate = params.get('sample_rate', 44100)
            x_data = np.arange(len(waveform), dtype=np.float64) / sample_rate
            x_label = '时间'
            x_unit = 's'
        else:
            x_data = np.arange(len(waveform), dtype=np.float64)
            x_label = '样本点'
            x_unit = ''

        # 设置X轴标签
        self.plot_widget.setLabel('bottom', x_label, x_unit)

        try:
            # 更新绘图数据
            self.plot_curve.setData(x_data, waveform)

            # 设置网格显示
            self.plot_widget.showGrid(x=params.get('show_grid', True),
                                      y=params.get('show_grid', True),
                                      alpha=0.3)

            # 设置坐标轴范围
            if params.get('auto_scale', True):
                # 自动缩放
                if len(waveform) > 0:
                    y_min, y_max = np.min(waveform), np.max(waveform)
                    y_margin = (y_max - y_min) * 0.1 if y_max != y_min else 0.1

                    # 确保范围合理
                    y_min = max(-20.0, y_min - y_margin)
                    y_max = min(20.0, y_max + y_margin)

                    self.plot_widget.setYRange(y_min, y_max)

                    if params.get('x_scroll', False):
                        # 滚动模式 - 显示最新的数据
                        x_max = x_data[-1] if len(x_data) > 0 else 1.0
                        display_time = params.get('display_time', 1.0)
                        self.plot_widget.setXRange(max(0, x_max - display_time), x_max)
                    else:
                        # 固定范围
                        display_time = params.get('display_time', 1.0)
                        x_max = min(display_time, x_data[-1]) if len(x_data) > 0 else display_time
                        self.plot_widget.setXRange(0, x_max)
            else:
                # 手动缩放
                y_range = params.get('y_range', 1.0)
                self.plot_widget.setYRange(-y_range, y_range)

                if params.get('x_scroll', False):
                    x_max = x_data[-1] if len(x_data) > 0 else 1.0
                    display_time = params.get('display_time', 1.0)
                    self.plot_widget.setXRange(max(0, x_max - display_time), x_max)
                else:
                    display_time = params.get('display_time', 1.0)
                    x_max = min(display_time, x_data[-1]) if len(x_data) > 0 else display_time
                    self.plot_widget.setXRange(0, x_max)

            # 更新状态
            display_time = params.get('display_time', 1.0)
            sample_rate = params.get('sample_rate', 44100)
            self.status_label.setText(
                f"显示 {len(waveform)} 个样本点 | "
                f"时间范围: {display_time}秒 | "
                f"采样率: {sample_rate} Hz"
            )

        except Exception as e:
            print(f"更新波形显示时出错: {e}")
            # 出错时重置显示
            self.plot_curve.clear()
            self.status_label.setText(f"显示错误: {str(e)}")

    def on_auto_scale_changed(self, checked):
        """自动缩放改变"""
        if self.updating_from_ui:
            return

        self.display_params['auto_scale'] = checked
        self.update_controls()
        self.update_display()

        # 通知处理器参数改变
        if self.processor and not self.updating_from_processor:
            self.processor.update_parameter_from_display('auto_scale', checked)

    def on_display_time_changed(self, value):
        """显示时间改变"""
        if self.updating_from_ui:
            return

        self.display_params['display_time'] = value
        self.update_display()

        # 通知处理器参数改变
        if self.processor and not self.updating_from_processor:
            self.processor.update_parameter_from_display('display_time', value)

    def on_y_range_changed(self, value):
        """Y轴范围改变"""
        if self.updating_from_ui:
            return

        self.display_params['y_range'] = value
        self.update_display()

        # 通知处理器参数改变
        if self.processor and not self.updating_from_processor:
            self.processor.update_parameter_from_display('y_range', value)

    def on_x_axis_changed(self, text):
        """X轴坐标模式改变"""
        if self.updating_from_ui:
            return

        self.display_params['x_axis_mode'] = 'time' if text == '时间' else 'samples'
        self.update_display()

        # 通知处理器参数改变
        if self.processor and not self.updating_from_processor:
            self.processor.update_parameter_from_display('x_axis_mode', self.display_params['x_axis_mode'])

    def on_x_scroll_changed(self, checked):
        """X轴滚动改变"""
        if self.updating_from_ui:
            return

        self.display_params['x_scroll'] = checked
        self.update_display()

        # 通知处理器参数改变
        if self.processor and not self.updating_from_processor:
            self.processor.update_parameter_from_display('x_scroll', checked)

    def on_grid_changed(self, checked):
        """网格显示改变"""
        if self.updating_from_ui:
            return

        self.display_params['show_grid'] = checked
        self.update_display()

        # 通知处理器参数改变
        if self.processor and not self.updating_from_processor:
            self.processor.update_parameter_from_display('show_grid', checked)

    def on_parameter_updated_from_processor(self, param_name, value):
        """从处理器接收参数更新"""
        self.updating_from_processor = True

        if param_name in self.display_params:
            self.display_params[param_name] = value
            self.update_controls()
            self.update_display()

        self.updating_from_processor = False

    def on_processor_parameters_updated(self, new_parameters):
        """处理器参数更新回调 - 修复崩溃问题"""
        if not new_parameters or not isinstance(new_parameters, dict):
            print(f"警告: 接收到无效的参数: {new_parameters}")
            return

        self.updating_from_processor = True

        try:
            for param_name, value in new_parameters.items():
                if param_name in self.display_params:
                    # 验证参数值类型
                    if param_name == 'auto_scale' and isinstance(value, bool):
                        self.display_params[param_name] = value
                    elif param_name == 'display_time' and isinstance(value, (int, float)):
                        self.display_params[param_name] = float(value)
                    elif param_name == 'y_range' and isinstance(value, (int, float)):
                        self.display_params[param_name] = float(value)
                    elif param_name == 'x_axis_mode' and value in ['time', 'samples']:
                        self.display_params[param_name] = value
                    elif param_name == 'x_scroll' and isinstance(value, bool):
                        self.display_params[param_name] = value
                    elif param_name == 'show_grid' and isinstance(value, bool):
                        self.display_params[param_name] = value
                    elif param_name == 'sample_rate' and isinstance(value, int):
                        self.display_params[param_name] = value
                    else:
                        print(f"警告: 忽略无效参数 {param_name}: {value} (类型: {type(value)})")

            self.update_controls()
            self.update_display()

        except Exception as e:
            print(f"处理参数更新时出错: {e}")
            import traceback
            traceback.print_exc()
        finally:
            self.updating_from_processor = False

    def set_theme(self, theme):
        """设置主题 - 增强版本"""
        if theme == "light":
            self.plot_widget.setBackground('w')
            # 设置绘图区域样式
            self.plot_widget.getPlotItem().getViewBox().setBackgroundColor((240, 240, 240))
            # 设置坐标轴样式
            self._apply_light_theme_to_plot()
            # 设置控件样式
            self._apply_light_theme_to_controls()
        else:
            self.plot_widget.setBackground('k')
            # 设置绘图区域样式
            self.plot_widget.getPlotItem().getViewBox().setBackgroundColor((40, 40, 40))
            # 设置坐标轴样式
            self._apply_dark_theme_to_plot()
            # 设置控件样式
            self._apply_dark_theme_to_controls()

    def _apply_light_theme_to_plot(self):
        """应用白天主题到绘图区域"""
        # 设置坐标轴颜色
        self.plot_widget.getAxis('left').setPen('k')
        self.plot_widget.getAxis('bottom').setPen('k')
        self.plot_widget.getAxis('left').setTextPen('k')
        self.plot_widget.getAxis('bottom').setTextPen('k')

        # 设置网格颜色
        self.plot_widget.showGrid(x=True, y=True, alpha=0.3)

        # 设置曲线颜色
        self.plot_curve.setPen(pg.mkPen(color='b', width=1))

    def _apply_dark_theme_to_plot(self):
        """应用黑夜主题到绘图区域"""
        # 设置坐标轴颜色
        self.plot_widget.getAxis('left').setPen('w')
        self.plot_widget.getAxis('bottom').setPen('w')
        self.plot_widget.getAxis('left').setTextPen('w')
        self.plot_widget.getAxis('bottom').setTextPen('w')

        # 设置网格颜色
        self.plot_widget.showGrid(x=True, y=True, alpha=0.3)

        # 设置曲线颜色
        self.plot_curve.setPen(pg.mkPen(color=(100, 150, 255), width=1))

    def _apply_light_theme_to_controls(self):
        """应用白天主题到控件 - 更新范围限制的样式"""
        self.setStyleSheet("""
            QMainWindow {
                background-color: #f0f0f0;
                color: #000000;
            }
            QGroupBox {
                color: #000000;
                border: 1px solid #c0c0c0;
                border-radius: 5px;
                margin-top: 1ex;
                font-weight: bold;
                background-color: #f8f8f8;
            }
            QGroupBox::title {
                subcontrol-origin: margin;
                subcontrol-position: top center;
                padding: 0 5px;
                background-color: #f8f8f8;
            }
            QCheckBox {
                color: #000000;
            }
            QCheckBox::indicator {
                width: 13px;
                height: 13px;
            }
            QCheckBox::indicator:unchecked {
                border: 1px solid #c0c0c0;
                background-color: #ffffff;
            }
            QCheckBox::indicator:checked {
                border: 1px solid #8080ff;
                background-color: #8080ff;
            }
            QLabel {
                color: #000000;
            }
            QDoubleSpinBox, QComboBox {
                background-color: #ffffff;
                color: #000000;
                border: 1px solid #c0c0c0;
                border-radius: 3px;
                padding: 2px 5px;
                min-width: 70px;  /* 确保宽度足够显示数值 */
            }
            QDoubleSpinBox:focus, QComboBox:focus {
                border: 1px solid #8080ff;
                background-color: #ffffe0;
            }
            QDoubleSpinBox:disabled, QComboBox:disabled {
                background-color: #e8e8e8;
                color: #808080;
                border: 1px solid #c8c8c8;
            }
            QPushButton {
                background-color: #e0e0e0;
                color: #000000;
                border: 1px solid #c0c0c0;
                border-radius: 3px;
                padding: 5px 10px;
                font-weight: bold;
            }
            QPushButton:hover {
                background-color: #d0d0d0;
            }
            QPushButton:pressed {
                background-color: #c0c0c0;
            }
            QPushButton:disabled {
                background-color: #e8e8e8;
                color: #a0a0a0;
                border: 1px solid #d0d0d0;
            }
            QStatusBar {
                background-color: #e0e0e0;
                color: #000000;
                border-top: 1px solid #c0c0c0;
            }
        """)

    def _apply_dark_theme_to_controls(self):
        """应用黑夜主题到控件 - 更新范围限制的样式"""
        self.setStyleSheet("""
            QMainWindow {
                background-color: #2b2b2b;
                color: #ffffff;
            }
            QGroupBox {
                color: #ffffff;
                border: 1px solid #555555;
                border-radius: 5px;
                margin-top: 1ex;
                font-weight: bold;
                background-color: #353535;
            }
            QGroupBox::title {
                subcontrol-origin: margin;
                subcontrol-position: top center;
                padding: 0 5px;
                background-color: #353535;
            }
            QCheckBox {
                color: #ffffff;
            }
            QCheckBox::indicator {
                width: 13px;
                height: 13px;
            }
            QCheckBox::indicator:unchecked {
                border: 1px solid #777777;
                background-color: #353535;
            }
            QCheckBox::indicator:checked {
                border: 1px solid #7777ff;
                background-color: #7777ff;
            }
            QLabel {
                color: #ffffff;
            }
            QDoubleSpinBox, QComboBox {
                background-color: #454545;
                color: #ffffff;
                border: 1px solid #555555;
                border-radius: 3px;
                padding: 2px 5px;
                min-width: 70px;  /* 确保宽度足够显示数值 */
            }
            QDoubleSpinBox:focus, QComboBox:focus {
                border: 1px solid #7777ff;
                background-color: #505050;
            }
            QDoubleSpinBox:disabled, QComboBox:disabled {
                background-color: #3a3a3a;
                color: #808080;
                border: 1px solid #454545;
            }
            QPushButton {
                background-color: #404040;
                color: #ffffff;
                border: 1px solid #555555;
                border-radius: 3px;
                padding: 5px 10px;
                font-weight: bold;
            }
            QPushButton:hover {
                background-color: #505050;
            }
            QPushButton:pressed {
                background-color: #606060;
            }
            QPushButton:disabled {
                background-color: #353535;
                color: #707070;
                border: 1px solid #454545;
            }
            QStatusBar {
                background-color: #3c3c3c;
                color: #ffffff;
                border-top: 1px solid #555555;
            }
        """)

    def closeEvent(self, event):
        """关闭事件"""
        # 清理资源
        if hasattr(self, 'plot_curve'):
            self.plot_curve.clear()
        
        # 发送窗口关闭信号
        if hasattr(self, 'node_id'):
            self.window_closed.emit(self.node_id)
        
        event.accept()

    # def set_processing_state(self, is_running):
    #     """设置处理运行状态，用于启用/禁用控件"""
    #     self.is_processing_running = is_running
    #     self._update_controls_enabled_state()

    # def _update_controls_enabled_state(self):
    #     """更新控件的启用状态"""
    #     enabled = not self.is_processing_running
    #
    #     # 更新所有控件的启用状态
    #     if hasattr(self, 'display_time_spin'):
    #         self.display_time_spin.setEnabled(enabled)
    #
    #     if hasattr(self, 'y_range_spin'):
    #         self.y_range_spin.setEnabled(enabled)
    #
    #     if hasattr(self, 'auto_scale_check'):
    #         self.auto_scale_check.setEnabled(enabled)
    #
    #     if hasattr(self, 'x_axis_combo'):
    #         self.x_axis_combo.setEnabled(enabled)
    #
    #     if hasattr(self, 'x_scroll_check'):
    #         self.x_scroll_check.setEnabled(enabled)
    #
    #     if hasattr(self, 'grid_check'):
    #         self.grid_check.setEnabled(enabled)
    #
    #     # 更新状态栏提示
    #     if hasattr(self, 'status_label'):
    #         current_text = self.status_label.text()
    #         if self.is_processing_running and "运行中" not in current_text:
    #             self.status_label.setText(current_text + " | 运行中，设置已锁定")
    #         elif not self.is_processing_running and "运行中" in current_text:
    #             new_text = current_text.split(" | ")[0]
    #             self.status_label.setText(new_text)